home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / LONGDOS.ASM < prev    next >
Assembly Source File  |  1997-03-10  |  16KB  |  856 lines

  1. ; This is a replacement for DOS C RTL system functions, which detects
  2. ; presence of DOS 7/Chickago Long File Name (LFN) service and use new
  3. ; or old interrupt calls respectively to provide uniform interface.
  4. ; Directory service is tuned for usage with Portable tar program.
  5. ; In particular:
  6. ; 1) it always tries FCB-style calls in order to obtain starting cluster
  7. ;    number (which further used as a part of unique file id),
  8. ; 2) thus it is constrained to current directory,
  9. ; 3) if cluster number is available then the package tries to resolve
  10. ;    substituted drives and get "real" drive number,
  11. ; 4) the package automatically converts file names to lowercase even
  12. ;    under DOS 7 until it is really new style name.
  13.  
  14.         include    farnear.inc
  15.  
  16. _DATA        segment    word public 'DATA'
  17. xfcb_buf    db    (7+37) dup (0)
  18. search_buf    db    (44+260+14) dup (0)
  19. longname_buf    equ    search_buf + 44
  20. oldname_buf    equ    longname_buf + 260
  21.  
  22.         public    _lfn_active
  23. _lfn_active    db    255
  24. _DATA        ends
  25.  
  26.     routine    __IOERROR    ; extern int pascal __IOerror()
  27.  
  28. _TEXT        segment    byte public 'CODE'
  29.         assume    cs:_TEXT, ds:NOTHING, es:_DATA
  30.  
  31.     program    _dosgetdisk
  32.         mov    ah,19h
  33.         int    21h
  34.         cbw
  35.         ret
  36. _dosgetdisk    endp
  37.  
  38.     program    _dossetdisk
  39.         push    bp
  40.         mov    bp,sp
  41.         mov    dl,arglist[0]    ; DL = drive
  42.         mov    ah,0Eh
  43.         int    21h
  44. ; no error status available - explicitly verify the result
  45.         mov    ah,19h        ; get drive
  46.         int    21h
  47.         xor    al,arglist[0]
  48.         jz    disk_end
  49. ; do not bother to set errno
  50.         mov    al,-1
  51. disk_end:    cbw
  52.         pop    bp
  53.         ret
  54. _dossetdisk    endp
  55.  
  56. seg_DATA    dw    _DATA
  57.  
  58. ldata        macro    rs
  59.         mov    rs,cs:seg_DATA
  60.         endm
  61.  
  62. check_dos    proc    near
  63.         ldata    es
  64.         cmp    byte ptr es:_lfn_active,0
  65.         ret
  66. check_dos    endp
  67.  
  68. check_err    proc    near
  69.         cmp    byte ptr es:_lfn_active,0
  70.         jg    is_error
  71.         cmp    ah,71h
  72.         jne    is_error
  73.         mov    byte ptr es:_lfn_active,0
  74.         clc
  75.         ret
  76. is_error:    stc
  77.         ret
  78. check_err    endp
  79.  
  80. set_newdos    proc    near
  81.         mov    byte ptr es:_lfn_active,1
  82.         ret
  83. set_newdos    endp
  84.  
  85.     program    _lgetcurdir
  86. ; int lgetcurdir(int drive, char far *dest)
  87.         push    bp
  88.         mov    bp,sp
  89.         push    si
  90.         push    ds
  91.  
  92.         mov    dx,arglist[0]
  93.         lds    si,arglist[2]
  94.         call    check_dos
  95.         je    short pwd_old
  96.  
  97.         mov    ax,7147h    ; get long cwd
  98.         stc
  99.         int    21h
  100.         jc    short pwd_check
  101.         call    set_newdos
  102.         jmp    short pwd_ok
  103. pwd_check:
  104.         call    check_err
  105.         jc    short pwd_error
  106. pwd_old:
  107.         mov    ah,47h        ; get cwd - old style
  108.         int    21h
  109.         jnc    pwd_ok
  110. pwd_error:    pop    ds
  111.         push    ax
  112.         call    __IOERROR
  113.         jmp    short pwd_end
  114. pwd_ok:        xor    ax,ax        ; AX := 0
  115.         pop    ds
  116. pwd_end:    pop    si
  117.         pop    bp
  118.         ret
  119.  
  120. _lgetcurdir    endp
  121.  
  122.     program    _laction
  123. ; int laction(int a, char far *path)
  124.         push    bp
  125.         mov    bp,sp
  126.         push    ds
  127.  
  128.         mov    cx,arglist[0]
  129.         lds    dx,arglist[2]
  130. do_action:
  131.         call    check_dos
  132.         je    short act_old
  133.  
  134.         mov    al,cl        ; action
  135.         mov    ah,71h        ; long filename call
  136.         stc
  137.         int    21h
  138.         jc    short check_act
  139.         call    set_newdos
  140.         jmp    short act_ok
  141. check_act:
  142.         call    check_err
  143.         jc    short act_error
  144. act_old:
  145.         mov    ah,cl
  146.         int    21h
  147.         jnc    act_ok
  148. act_error:    pop    ds
  149.         push    ax
  150.         call    __IOERROR
  151.         jmp    short act_end
  152. act_ok:        xor    ax,ax        ; AX := 0
  153.         pop    ds
  154. act_end:    pop    bp
  155.         ret
  156. _laction    endp
  157.  
  158.     program _lopen4
  159. ; int lopen4(char far *filename, int mode, int action, int attributes)
  160.         push    bp
  161.         mov    bp,sp
  162.         push    si
  163.         push    ds
  164.  
  165. mode        equ    arglist[4]
  166. action        equ    arglist[6]
  167. attribute    equ    arglist[8]
  168.  
  169.         lds    si,arglist[0]    ; DS:SI => file name
  170.         call    check_dos
  171.         je    short old_open
  172.         mov    bx,mode
  173.         mov    dx,action
  174.         mov    cx,attribute
  175.         mov    ax,716Ch
  176.         stc
  177.         int    21h
  178.         jc    short check_open
  179.         call    set_newdos
  180.         jmp    short open_end
  181. check_open:
  182.         call    check_err
  183.         jc    short open_error
  184. old_open:
  185.         mov    dx,si        ; DS:DX => file name
  186.         mov    ax,action
  187.         cmp    ax,2
  188.         je    short existance
  189.         cmp    ax,16
  190.         je    short existance
  191.         cmp    ax,18
  192.         je    short do_create
  193.         and    al,not 16
  194.         dec    ax        ; 1 or 17
  195.         jz    short do_open
  196.         mov    al,1        ; invalid action code
  197.         jmp    short bad_open
  198. existance:
  199.         mov    ax,4300h    ; get file attributes
  200.         int    21h
  201.         jc    short file_unavailable
  202. ; file exists, do we like to truncate it?
  203.         test    byte ptr action,2
  204.         jnz    short do_create
  205.         mov    al,5
  206.         jmp    short bad_open
  207. do_open:
  208.         mov    ax,mode
  209.         mov    ah,3Dh
  210.         int    21h
  211.         jnc    short open_end
  212. file_unavailable:
  213.         cmp    ax,2        ; check the error code
  214.         jne    short open_error
  215. ; file does not exist, do we like to create it?
  216.         test    byte ptr action,16
  217.         jz    short open_error
  218. do_create:
  219.         mov    cx,attribute
  220.         mov    ah,3Ch        ; create/overwrite
  221.         int    21h
  222.         jnc    short open_end
  223. bad_open:
  224.         cbw
  225. open_error:
  226.         pop    ds        ; restore data segment
  227.         push    ax
  228.         call    __IOERROR
  229.         push    ds        ; adjustment dummy
  230. open_end:                ; return the file handle
  231.         pop    ds
  232.         pop    si
  233.         pop    bp
  234.         ret
  235. _lopen4        endp
  236.  
  237.     program    _dosclose
  238. ; int dosclose(int handle)
  239.         push    bp
  240.         mov    bp,sp
  241.         mov    bx,arglist[0]
  242.         pop    bp
  243.         mov    ah,3Eh
  244.         int    21h
  245.         jc    short close_error
  246.         xor    ax,ax
  247.         ret
  248. close_error:
  249.         push    ax
  250.         call    __IOERROR
  251.         ret
  252. _dosclose    endp
  253.  
  254.     program    _doswrite
  255. ; int doswrite(int handle, void far *buffer, unsigned length)
  256.         mov    ah,40h
  257.         jmp    short do_io
  258. _doswrite    endp
  259.  
  260.     program    _dosread
  261. ; int dosread(int handle, void far *buffer, unsigned length)
  262.         mov    ah,3fh
  263. do_io:        push    bp
  264.         mov    bp,sp
  265.         push    ds
  266.         mov    bx,arglist[0]    ; handle
  267.         lds    dx,arglist[2]    ; buffer
  268.         mov    cx,arglist[6]    ; length
  269.         int    21h
  270.         jnc    short io_end
  271.         pop    ds        ; restore data segment
  272.         push    ax
  273.         call    __IOERROR
  274.         push    ds        ; adjustment dummy
  275. io_end:        pop    ds        ; return number of bytes
  276.         pop    bp
  277.         ret
  278. _dosread    endp
  279.  
  280.     program    _dosseek
  281. ; long dosseek(int handle, long offs, int whence)
  282.         push    bp
  283.         mov    bp,sp
  284.         mov    bx,arglist[0]    ; handle
  285.         mov    dx,arglist[2]    ; offset, low
  286.         mov    cx,arglist[4]    ; offset, high
  287.         mov    ax,arglist[6]    ; whence
  288.         pop    bp
  289.         mov    ah,42h
  290.         int    21h
  291.         jnc    short seek_end
  292.         push    ax
  293.         call    __IOERROR
  294.         cwd
  295. seek_end:    ret
  296. _dosseek    endp
  297.  
  298.     program    _lchmod
  299. ; int lchmod(char far *filename, int op, int mode)
  300.         push    bp
  301.         mov    bp,sp
  302.         push    ds
  303.  
  304. action        equ    arglist[4]
  305.  
  306.         lds    dx,arglist[0]    ; DS:DX => file name
  307.         mov    bx,action
  308.         mov    cx,arglist[6]    ; CX := mode
  309.         call    check_dos
  310.         je    short old_ch
  311.         mov    ax,7143h
  312.         stc
  313.         int    21h
  314.         jc    short check_ch
  315.         call    set_newdos
  316.         jmp    short ch_ok
  317. check_ch:
  318.         call    check_err
  319.         jc    short ch_error
  320. old_ch:
  321.         xchg    ax,bx        ; BL := action
  322.         mov    ah,43h
  323.         int    21h
  324.         jc    short ch_error
  325. ch_ok:        xor    ax,ax
  326.         test    byte ptr action,1
  327.         jz    short ch_end
  328.         xchg    ax,cx
  329. ch_end:        pop    ds
  330.         pop    bp
  331.         ret
  332. ch_error:
  333.         pop    ds        ; restore data segment
  334.         push    ax
  335.         call    __IOERROR
  336.         pop    bp
  337.         ret
  338. _lchmod        endp
  339.  
  340. local_dta    proc    near
  341.         ldata    ds
  342.         lea    dx,_DATA:xfcb_buf
  343.         mov    ah,1Ah    ; set DTA
  344.         int    21h
  345.         ret
  346. local_dta    endp
  347.  
  348. set_dta        macro
  349.         mov    ah,2fh
  350.         int    21h
  351.         push    es    ; preserve DTA
  352.         push    bx
  353.  
  354.         call    local_dta
  355.         endm
  356.  
  357. reset_dta    macro
  358.         pop    dx
  359.         pop    ds
  360.         mov    ah,1Ah    ; restore DTA
  361.         int    21h
  362.         endm
  363.  
  364. old_find1st    proc    near
  365. ; int near pascal old_find1st(void far *fcbP, char far *nameP)
  366. ; CL = attributes mask
  367.         push    bp
  368.         mov    bp,sp
  369.  
  370. fcbP        equ    ss:bp[4]
  371. nameP        equ    ss:bp[8]
  372.  
  373.         push    si
  374.         push    di
  375.         lds    si,nameP
  376.         les    di,fcbP
  377.         mov    byte ptr es:[di],-1    ; mark an extended FCB
  378.         mov    es:[di+6],cl
  379.         add    di,7            ; ES:DI => regular FCB
  380.         mov    byte ptr es:[di],0
  381.         mov    ax,2900h
  382.         int    21h            ; build FCB
  383.         pop    di
  384.         pop    si
  385.  
  386.         set_dta
  387.         ldata    es
  388.         lea    bx,_DATA:xfcb_buf
  389.         mov    ah,11h
  390. find_loop:
  391.         lds    dx,fcbP
  392.         int    21h    ; perform search
  393.         test    al,al
  394.         jnz    short find_done
  395. ; ignore LFN records
  396.         cmp    word ptr es:bx[8+26],0
  397.         jne    short find_done
  398.         cmp    byte ptr es:bx[8+11],15
  399.         jne    short find_done
  400.         mov    ah,12h
  401.         jmp    short find_loop
  402. find_done:
  403.         xchg    ax,bp    ; preserve the result
  404.         reset_dta
  405.  
  406.         xchg    ax,bp    ; restore result
  407.         test    al,al
  408.         pop    bp
  409.         ret    8
  410. old_find1st    endp
  411.  
  412. verify_drive    proc    near
  413. ; convert virtual (substed etc.) drive number to real one
  414.         ldata    es
  415.         lea    di,es:xfcb_buf+7
  416.         mov    dl,es:[di]
  417.         mov    ah,32h
  418.         int    21h
  419.         test    al,al
  420.         jnz    drive_done
  421.         mov    al,ds:[bx]
  422.         inc    ax
  423.         mov    es:[di],al
  424. drive_done:    ret
  425. verify_drive    endp
  426.  
  427. verify_subst    proc    near
  428. ; same as above, but for LFN-DOS
  429.         ldata    es
  430.         lea    di,es:xfcb_buf+7
  431. subst_loop:
  432.         mov    bl,es:di
  433.         mov    bh,2
  434.         mov    ax,71AAh
  435.         stc
  436.         int    21h
  437.         jc    short subst_done
  438.         mov    bx,dx
  439.         mov    al,ds:bx
  440.         and    al,not ('z'-'Z')
  441.         cmp    al,'Z'
  442.         ja    subst_done
  443.         sub    al,'A'
  444.         jb    subst_done
  445.         cmp    byte ptr ds:[bx+1],':'
  446.         jne    subst_done
  447.         inc    ax    ; AL := new drive number
  448.         cmp    al,es:di
  449.         je    short subst_done
  450.         mov    es:di,al
  451.         jmp    short subst_loop
  452. subst_done:    ret
  453. verify_subst    endp
  454.  
  455. fill_buf    proc    near
  456. ; CX = Unicode conversion flags
  457. ; DS:DI = cwdentP
  458.         mov    dx,_DATA
  459.         lea    bx,_DATA:longname_buf
  460.         mov    ds:di[0],bx
  461.         mov    ds:di[2],dx
  462.         lea    bx,_DATA:xfcb_buf+7
  463.         mov    ds:di[4],bx
  464.         mov    ds:di[6],dx
  465.  
  466.         assume    ds:_DATA
  467.         mov    ds,dx
  468. ; if volume label is set, always fake FCB
  469.         xor    ax,ax
  470.         test    byte ptr ds:search_buf,8
  471.         jnz    short fcb_hook
  472.         lea    bx,_DATA:oldname_buf
  473.         cmp    byte ptr ds:[bx],0
  474.         je    short one_name
  475.         test    cl,2        ; is shortname realistic?
  476.         jnz    short fake_fcb
  477.         jmp    short fill_fcb
  478. ; names are the same, use new one
  479. one_name:    sub    bx,oldname_buf-longname_buf
  480.         mov    si,bx
  481. lc_loop:    lodsb            ; convert it to lowercase
  482.         cmp    al,'A'
  483.         jb    short lc_next
  484.         cmp    al,'Z'
  485.         ja    short lc_next
  486.         add    al,'z'-'Z'
  487.         mov    ds:[si-1],al
  488. lc_next:    test    al,al
  489.         jnz    short lc_loop
  490.  
  491.         test    cl,1
  492.         jnz    short fake_fcb
  493. ; use old-style call to fill FCB
  494. fill_fcb:
  495.         push    ds
  496.         push    bx
  497.         push    ds
  498.         lea    bx,_DATA:xfcb_buf
  499.         push    bx
  500.         mov    cl,ds:search_buf
  501.         call    old_find1st
  502.         jnz    short fake_fcb
  503.         call    verify_subst
  504.         ret
  505. fake_fcb:
  506.         mov    ax,-1
  507. fcb_hook:
  508.         ldata    ds
  509.         lea    bx,_DATA:search_buf
  510.         lea    di,_DATA:xfcb_buf+7
  511.         mov    ds:di[1+26],ax    ; cluster
  512.  
  513.         mov    ah,19h
  514.         int    21h        ; get current drive
  515.         inc    ax
  516. ; do not care to use real drive for fake FCB
  517.         mov    ds:[di],al    ; store it to FCB
  518.  
  519.         mov    al,ds:bx
  520.         mov    ds:di[1+11],al    ; attributes
  521.         mov    ax,ds:bx[20]
  522.         mov    ds:di[1+22],ax    ; time
  523.         mov    ax,ds:bx[22]
  524.         mov    ds:di[1+24],ax    ; date
  525.         mov    ax,ds:bx[32]
  526.         mov    ds:di[1+28],ax    ; size, low
  527.         mov    ax,ds:bx[34]
  528.         mov    ds:di[1+30],ax    ; size, high
  529.         ret
  530.         assume    ds:NOTHING
  531. fill_buf    endp
  532.  
  533. copy_name    proc    near
  534.         mov    bx,cx    ; preserve count
  535. copy_loop:
  536.         lodsb
  537.         test    al,al
  538.         jz    short copy_done
  539.         test    dl,dl
  540.         jnz    short copy_char
  541.         cmp    al,'A'
  542.         jb    short copy_char
  543.         cmp    al,'Z'
  544.         ja    short copy_char
  545.         add    al,'z'-'Z'
  546. copy_char:    stosb
  547.         loop    short copy_loop
  548. copy_done:
  549.         neg    cx
  550.         add    cx,bx
  551.         jcxz    short strip_done
  552. strip_sp:    cmp    byte ptr es:[di-1],' '
  553.         jne    short strip_done
  554.         dec    di
  555.         loop    short strip_sp
  556. strip_done:
  557.         ret
  558. copy_name    endp
  559.  
  560. prepare_name    proc    near
  561. ; DS:SI = cwdentP
  562.         mov    ax,_DATA
  563.         mov    es,ax
  564.         lea    di,_DATA:longname_buf
  565.         lea    bx,_DATA:xfcb_buf+7
  566.         mov    ds:si[0],di
  567.         mov    ds:si[2],es
  568.         mov    ds:si[4],bx
  569.         mov    ds:si[6],es
  570.  
  571.         mov    ds,ax    ; DS := _DATA
  572.         mov    dl,ds:bx[1+11]
  573.         and    dl,8    ; isolate label attribute
  574.         lea    si,[bx+1]    ; DS:SI => file name in FCB
  575.         mov    cx,8
  576.         call    copy_name
  577.  
  578.         mov    bx,si
  579.         mov    cx,3
  580. check_ext:
  581.         lodsb
  582.         test    al,al
  583.         jz    short ext_done
  584.         cmp    al,' '
  585.         jne    short have_ext
  586.         loop    check_ext
  587.         jmp    short ext_done
  588. have_ext:
  589.         mov    al,'.'
  590.         stosb
  591.         mov    si,bx
  592.         mov    cx,3
  593.         call    copy_name
  594. ext_done:
  595.         xor    al,al
  596.         stosb
  597.         ret
  598. prepare_name    endp
  599.  
  600.     program _lfindfirst
  601. ; int lfindfirst(lcwdent_t far *cdwentP, char far *pattern, int attribute)
  602.         push    bp
  603.         mov    bp,sp
  604.         push    si
  605.         push    di
  606.         push    ds
  607.  
  608. cwdentP        equ    arglist[0]
  609. pattern        equ    arglist[4]
  610. attribute    equ    arglist[8]
  611.  
  612.         call    check_dos
  613.         je    short old_search
  614.  
  615.         lds    dx,pattern
  616.         lea    di,es:search_buf    ; ES:DI => buf
  617.         mov    byte ptr es:oldname_buf,0
  618.         mov    si,1            ; DOS time format
  619.         mov    cx,attribute
  620.         mov    ax,714Eh
  621.         stc
  622.         int    21h
  623.         ldata    es
  624.         lds    di,cwdentP
  625.         jc    short check_search
  626.         call    set_newdos
  627.         mov    ds:di[8],ax    ; preserve handle
  628.         call    fill_buf
  629.         jmp    short search_ok
  630. check_search:
  631.         call    check_err
  632.         jnc    short old_search
  633.         cmp    ax,2    ; file not found?
  634.         jne    short search_err
  635. ; assume it is short name, try old-style search
  636.         mov    word ptr ds:di[8],-1    ; invalidate handle
  637.         lea    bx,_DATA:xfcb_buf    ; ES:BX => scratch
  638.         jmp    short old_hook
  639. old_search:
  640.         les    bx,cwdentP
  641.         add    bx,8            ; ES:BX => xFCB buffer
  642. old_hook:
  643.         push    pattern[2]
  644.         push    pattern[0]
  645.         push    es
  646.         push    bx
  647.         mov    cl,attribute
  648.         call    old_find1st
  649.         jz    short use_fcb
  650.         mov    ax,2
  651. search_err:
  652.         pop    ds
  653.         push    ax
  654.         call    __IOERROR
  655.         jmp    short search_end
  656. use_fcb:
  657.         lds    si,cwdentP
  658.         call    prepare_name
  659.         call    verify_drive
  660. search_ok:
  661.         xor    ax,ax
  662.         pop    ds
  663. search_end:
  664.         pop    di
  665.         pop    si
  666.         pop    bp
  667.         ret
  668. _lfindfirst    endp
  669.  
  670.     program    _lfindnext
  671.         push    bp
  672.         mov    bp,sp
  673.         push    si
  674.         push    di
  675.         push    ds
  676.  
  677.         call    check_dos
  678.         je    short old_next
  679.         jg    short new_next
  680.         mov    ax,6        ; Hm-m
  681. next_err:
  682.         pop    ds
  683.         push    ax
  684.         call    __IOERROR
  685.         jmp    short next_end;
  686. new_next:
  687.         lds    si,arglist[0]
  688.         mov    bx,ds:si[8]    ; search handle
  689.         lea    di,_DATA:search_buf
  690.         mov    si,1        ; DOS time format
  691.         mov    ax,714fh
  692.         stc
  693.         int    21h
  694.         jc    next_err
  695.         lds    di,arglist[0]
  696.         call    fill_buf
  697.         jmp    short next_ok
  698. old_next:
  699.         set_dta
  700.         ldata    es
  701.         lea    bx,_DATA:xfcb_buf
  702. next_loop:
  703.         lds    dx,arglist[0]
  704.         add    dx,8    ; DS:DX => FCB from previous search
  705.         mov    ah,12h    ; perform search
  706.         int    21h
  707.         test    al,al
  708.         jnz    short next_done
  709. ; ignore LFN records
  710.         cmp    word ptr es:bx[8+26],0
  711.         jne    short next_done
  712.         cmp    byte ptr es:bx[8+11],15
  713.         je    short next_loop
  714. next_done:
  715.         xchg    ax,bx    ; preserve the result
  716.         reset_dta
  717.  
  718.         test    bl,bl
  719.         jz    short get_name
  720.         mov    ax,2
  721.         jmp    short next_err
  722. get_name:
  723.         lds    si,arglist[0]
  724.         call    prepare_name
  725.         call    verify_drive
  726. next_ok:
  727.         xor    ax,ax
  728.         pop    ds
  729. next_end:
  730.         pop    di
  731.         pop    si
  732.         pop    bp
  733.         ret
  734. _lfindnext    endp
  735.  
  736.     program    _lfindend
  737. ; int lfindend(lcwdent_t far *cdwentP)
  738.         call    check_dos
  739.         je    short finish_ok
  740.         jg    short do_fihish
  741. finish_fail:
  742.         mov    ax,6        ; Hm-m
  743. finish_err:
  744.         push    ax
  745.         call    __IOERROR
  746.         ret
  747. do_fihish:
  748.         push    bp
  749.         mov    bp,sp
  750.         les    bx,arglist[0]
  751.         pop    bp
  752.         mov    bx,es:bx[4]    ; remember the handle
  753.         stc
  754.         mov    ax,71A1h
  755.         int    21h
  756.         jc    short finish_err
  757. finish_ok:    xor    ax,ax
  758.         ret
  759. _lfindend    endp
  760.  
  761.     program    _lgetmtime
  762. ; int lgetmtime(char far *filename)
  763.         push    bp
  764.         mov    bp,sp
  765.         push    ds
  766.  
  767.         call    check_dos
  768.         je    short old_mt
  769.         lds    dx,arglist[0]    ; DS:DX => file name
  770.         mov    bl,4        ; get last write time
  771.         mov    ax,7143h
  772.         push    di
  773.         stc
  774.         int    21h
  775.         mov    dx,di
  776.         pop    di
  777.         jc    short check_mt
  778.         call    set_newdos
  779.         xchg    ax,cx
  780.         jmp    short mt_ok
  781. check_mt:
  782.         call    check_err
  783.         jnc    short old_mt
  784.         cmp    ax,2        ; assume it was an old name
  785.         jne    short mt_error
  786. old_mt:
  787.         set_dta
  788.  
  789.         lds    dx,arglist[0]    ; DS:DX => file name
  790.         mov    cx,3fh        ; any attribute
  791.         mov    ah,4fh
  792.         int    21h
  793.         jc    short mt_fail
  794.  
  795.         reset_dta
  796.  
  797.         ldata    ds
  798.         les    ax,dword ptr ds:xfcb_buf[22]
  799.         mov    dx,es
  800. mt_ok:
  801.         pop    ds
  802.         pop    bp
  803.         ret
  804. mt_fail:
  805.         xchg    ax,bx
  806.         reset_dta
  807.         xchg    ax,bx
  808. mt_error:
  809.         pop    ds        ; restore data segment
  810.         push    ax
  811.         call    __IOERROR
  812.         cwd
  813.         pop    bp
  814.         ret
  815. _lgetmtime    endp
  816.  
  817.     program    _lrename
  818. ; int lrename(char far *oldname, char far *newname)
  819.         push    bp
  820.         mov    bp,sp
  821.         push    di
  822.         push    ds
  823.  
  824.         lds    dx,arglist[0]
  825.         les    di,arglist[4]
  826.  
  827.         call    check_dos
  828.         je    short ren_old
  829.  
  830.         mov    ax,7156h
  831.         stc
  832.         int    21h
  833.         jc    short check_ren
  834.         call    set_newdos
  835.         jmp    short ren_ok
  836. check_ren:
  837.         call    check_err
  838.         jc    short ren_error
  839. ren_old:
  840.         mov    ah,56h
  841.         int    21h
  842.         jnc    ren_ok
  843. ren_error:    pop    ds
  844.         push    ax
  845.         call    __IOERROR
  846.         jmp    short ren_end
  847. ren_ok:        xor    ax,ax        ; AX := 0
  848.         pop    ds
  849. ren_end:    pop    di
  850.         pop    bp
  851.         ret
  852. _lrename    endp
  853.  
  854. _TEXT        ends
  855.         end
  856.